#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <algorithm>

const int MAXN = 5001;
const int MAXM = 200001;

int father[MAXN]{};

struct Edge {
	int u, v, w;  // u: 起点, v: 终点, w: 权重
} edges[MAXM];  // edges 是一个包含 MAXM 个 Edge 结构体的数组

int n, m;


void Build() {
	for (int i = 1; i <= n; i++) {
		father[i] = i;
	}
}

int Find(const int i) {
	if (i != father[i]) {
		father[i] = Find(father[i]);
	}
	return father[i];
}

bool Union(const int x, const int y) {
	const int fx = Find(x);
	const int fy = Find(y);
	if (fx != fy) {
		father[fx] = fy;
		return true;
	}
	return false;
}

inline bool MyCompare(const Edge& a, const Edge& b) {
	return a.w < b.w;
}

/**
 * 输入：
 * 4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3

输出：
7
 * @return

 测试链接 : https://www.luogu.com.cn/problem/P3366
 */
int main() {

	scanf("%d%d", &n, &m);

	Build();

	for (int i = 0; i < m; i++) {
		int x, y, z;
		scanf("%d%d%d", &edges[i].u, &edges[i].v, &edges[i].w);
	}

	std::sort(edges, edges + m, MyCompare);

	int ans = 0;
	int edgeCnt = 0;
	for (int i = 0; i < m; i++) {
		if (Union(edges[i].u, edges[i].v)) {
			edgeCnt++;
			ans += edges[i].w;
		}
	}

	if (edgeCnt == n - 1) {
		printf("%d\n", ans);
	}
	else {
		printf("%s\n", "orz");
	}

	return 0;
}